<?php

declare(strict_types=1);

namespace DreamCat\ApiDocLaravel;

use Dreamcat\ApiDoc\Popo\RouterEntranceDefinition;
use Dreamcat\ApiDoc\RouteDefineScanInterface;
use Illuminate\Support\Facades\Route;
use ReflectionException;
use ReflectionFunction;
use ReflectionMethod;

/**
 * Laravel路径扫描器
 * @author vijay
 */
class LaravelRouteScan implements RouteDefineScanInterface
{
    /** @var string 前缀地址 */
    private string $prefix;

    /**
     * 构造函数
     * @param string $prefix 前缀地址
     */
    public function __construct(string $prefix = "api")
    {
        $prefix = trim($prefix, " \t\n\r\0\x0B/");
        if ($prefix === "") {
            $this->prefix = "/";
        } else {
            $this->prefix = $prefix;
        }
    }

    /**
     * @inheritDoc
     * @throws ReflectionException
     */
    public function scanRouteList(string $projectPath): array
    {
        $list = [];
        foreach (Route::getRoutes()->getRoutes() as $route) {
            if (!str_starts_with($route->uri, $this->prefix)) {
                continue;
            }
            $uri = substr($route->uri, strlen($this->prefix));
            $ref = null;
            foreach ($route->methods() as $method) {
                if ($method === "HEAD") {
                    # 由于Laravel总是会把一个请求加上Head，所以需要排除
                    continue;
                }
                if (!$ref) {
                    if ($route->getAction("controller")) {
                        $ref = new ReflectionMethod($route->getController(), $route->getActionMethod());
                    } else {
                        $ref = new ReflectionFunction($route->getAction("uses"));
                    }
                }
                $def = new RouterEntranceDefinition();
                $def->setUri($uri)
                    ->setMethod($method)
                    ->setAction($ref);
                $list[] = $def;
            }
        }
        return $list;
    }
}

# end of file
